# Create your views here.

from models import All_Questions, User_Data, All_Answers, Staging
from random import sample
from django.shortcuts import render_to_response
from django.contrib.auth.forms import UserCreationForm
from django.contrib import auth
from django.http import HttpResponse
from django.http import HttpResponseRedirect
from django.contrib.auth.decorators import login_required
from django.db.models import F, Avg, Count
from django import template

register = template.Library()

import settings
from types import NoneType

# Get random set of questions
def get_random():
    # Get count for total number of questions
    totalNumberQuestions = All_Questions.objects.count()
    # Generate random ids in set 
    rand_ids = sample(range(0, totalNumberQuestions), totalNumberQuestions)
        # filter all objects by the random set
        # [:settings.QUIZ_SIZE] means only return this number from the set
    return All_Questions.objects.filter(id__in = rand_ids)[:settings.QUIZ_SIZE]
    
# view for template 
def get_random_questions(request):
    random_questions = get_random()
    return render_to_response('start_test.html', locals()) 



# Get random set of hardest questions
def get_hardest():
    # First we generate the 40 hardest questions
    ordered_questions = All_Questions.objects.order_by('-correct_percentage')[:settings.QUIZ_SIZE]
    # Now we ramdomise the set of questions 
    # Bit of pokery going on here but we convert the top 40 questions into a list and randomise
    # Flat = true implies the results are returned efficiently [1,2,3] as opposed to [(1,),(2,),(3,)]
    random_questions = All_Questions.objects.filter(pk__in=list(ordered_questions.values_list('id', flat=True))).order_by('?')  
    return random_questions

# Get random set of hardest questions
def get_easiest():
    # First we generate the 40 hardest questions
    ordered_questions = All_Questions.objects.order_by('correct_percentage')[:settings.QUIZ_SIZE]
    # Now we ramdomise the set of questions 
    # Bit of pokery going on here but we convert the top 40 questions into a list and randomise
    # Flat = true implies the results are returned efficiently [1,2,3] as opposed to [(1,),(2,),(3,)]
    random_questions = All_Questions.objects.filter(pk__in=list(ordered_questions.values_list('id', flat=True))).order_by('?')  
    return random_questions

def get_user_hardest(request):
    
    random_questions = []
    
    question_count = User_Data.objects.filter(user=request.user).annotate(Count('question'))
    if question_count >= settings.QUIZ_SIZE :
        ordered_questions = User_Data.objects.filter(user=request.user).order_by('-correct_percentage')[:settings.QUIZ_SIZE]
        random_questions = All_Questions.objects.filter(pk__in=list(ordered_questions.values_list('question_id', flat=True))).order_by('?')  
        return random_questions
    return get_hardest()


def get_hardest_questions(request):
    random_questions = get_hardest()
    return render_to_response('hardest_questions.html', locals())

def get_user_hardest_questions(request):
    random_questions = get_user_hardest(request)
    return render_to_response('hardest_questions.html', locals())

def get_easiest_questions(request):
    random_questions = get_easiest()
    return render_to_response('easiest_questions.html', locals())

def show_results(request):
    answers = request.POST.lists()
    incorrect_list = []
    wrong_answer = False
    stats = []
    user_results_list = []
    area_dict = {}

    # create skeleton results for graph
    # graph utility = (times used, times incorrect)
    for area_search in All_Questions.objects.get_areas() :
        area_dict[area_search] = graph_utility(0,0);
        
    # Loop through key value pairs
    for question_number, provided_answers in answers:
        # Get particular question from db
        question_number = question_number.lstrip('question_')
        q = All_Questions.objects.filter(id=question_number)[0]   
        
        # Get user results for area for graphing
        user_area_result = area_dict.get(q.area) 
            
        # Increment times used
        q.times_used = F('times_used')+1
        user_area_result.times_used += 1
        
        
        correct_answers = list(q.correct_answers_set.select_related().values_list('answer_id', flat=True))
        
        # Convert provided answers to integers for list comparison
        provided_answers_numeric = []
        correct_answers_numeric = []
        
        for i in provided_answers:
                provided_answers_numeric.append(int(i))
                
        for j in correct_answers:
                correct_answers_numeric.append(int(j))
        
        provided_answers_numeric.sort()
        correct_answers_numeric.sort()
            
        if(correct_answers_numeric != provided_answers_numeric):
                             

            # Create and append incorrect answer
            result = incorrect_answer(q.title, 
                                        All_Answers.objects.filter(id__in= provided_answers_numeric), 
                                            All_Answers.objects.filter(id__in= correct_answers_numeric).values_list('answer', flat=True), 
                                                q.area)
            incorrect_list.append(result)
            # Mark incorrect answer for stats
            # F() is an optimised update of a field
            q.times_incorrect = F('times_incorrect')+1
            user_area_result.times_incorrect += 1
        

        # Would be nicer to have a better way of getting this percentage other than this! 
        # Order_by is restrictive using the django model
        q.correct_percentage = ((q.times_used - q.times_incorrect)/q.times_used)*100
        
        
        # Save object  
        q.save()
          
        # if user is logged in we update their profile  
        if (request.user.is_authenticated()) :
            #check if this question has been answered in the user profile
            profile_entry, created = User_Data.objects.get_or_create(user=request.user, question=q, defaults={'times_incorrect' : 0, 'times_used' : 1})
            
            profile_entry.times_used = F('times_used')+1
            
            if(wrong_answer):
                profile_entry.times_used = F('times_incorrect')+1
           
            # Save object  
            profile_entry.correct_percentage = ((profile_entry.times_used - profile_entry.times_incorrect)/profile_entry.times_used)*100         
            profile_entry.save()
       
    first_test_check = 0

    # Get some statistics
    for area_search in All_Questions.objects.get_areas() :
        global_area_average = All_Questions.objects.filter(area=area_search).aggregate(Avg('correct_percentage')).values()
        global_area_average = 100 - int(global_area_average[0])
        # Get current test average
        current_test_area = area_dict.get(area_search)     
        current_test_average = 0
        r = current_test_area.times_used
        
        if(current_test_area.times_used != 0) :
            current_test_average = ((current_test_area.times_used - current_test_area.times_incorrect)/current_test_area.times_used)*100
        
        user_average = 0
        
        if(request.user.is_authenticated()):
            user_average = User_Data.objects.filter(question__area=area_search, user=request.user).aggregate(Avg('correct_percentage')).values()
            average_score_list=User_Data.objects.filter(user=request.user).aggregate(score = Avg('correct_percentage'))
            average_score = (str(round(average_score_list.__getitem__('score'),2)))
            
            if(user_average[0] is not None):
                    user_average = int(user_average[0])
            else:
                first_test_check += 1
            
        statistic = graph_stat(area_search, global_area_average, current_test_average, user_average)

        stats.append(statistic)
       
    overall_average_score_list = average_score_list=All_Questions.objects.aggregate(score = Avg('correct_percentage')) 
    overall_average_score = (str(round(overall_average_score_list.__getitem__('score'),2)))
           

    
    ## Assuming if the user has more than 2 areas not answered before it's his first time
    if(first_test_check >= 2):
        first_test = True
        
    a = incorrect_list.__len__()
    b = answers.__len__()
    
    if(a == 0 and b != 0):
        score = 100
    else:
        if(a == 0 and b == 0):
            score = 0
        else:
            score = round(100-((float(a)/float(b))*100), 2)
        
    # TODO remove ugly locals()
    return render_to_response('results.html', locals())
        

        
        
def create_user(request):
    if request.method == 'POST':
          form = UserCreationForm(request.POST)
          if form.is_valid():
                 new_user = form.save()
                 return HttpResponse("You're registered")
          else:
                 form = UserCreationForm()
                 return render_to_response("create_user.html", {'form': form})
    else:
        form = UserCreationForm()
        return render_to_response("create_user.html", {'form':form})
    
def login_authenticate(request):
    username = request.POST.get('username', '')
    password = request.POST.get('password', '') 
    user = auth.authenticate(username=username, password=password)
    if user is not None and user.is_active:
        auth.login(request, user)
        return HttpResponseRedirect('/start_test/')
    else:
        return render_to_response('invalid_login.html')

@login_required(redirect_field_name='redirect_to')
def user_profile(request):
    # add percentage correct
    # graph of areas
    user_percentage = User_Data.objects.filter(user=request.user).aggregate(Avg('correct_percentage'))
    user_spread = []
    return render_to_response('user_profile.html')  


class incorrect_answer(object):
    def __init__(self, title, provided_answer, correct_answer, question_area):
        self.title, self.provided_answer, self.correct_answer, self.question_area = title, provided_answer,correct_answer, question_area
        
class graph_stat(object):
    def __init__(self, question_area, avg_percentage, user_pct, user_av_pct):
        self.question_area, self.avg_percentage = question_area,  avg_percentage
        self.user_pct, self.user_av_pct = user_pct, user_av_pct
        
class graph_utility(object):
    def __init__(self, times_used, times_incorrect):
        self.times_used, self.times_incorrect = times_used, times_incorrect
        
def logout_view(request):
    auth.logout(request)
    return HttpResponseRedirect("/start_test/")

def landing_page(theRequest):
    return render_to_response("index.html")


def create_new_questions_from_staging(request):
    question_id = 1
    correct_answer_id = 1
    answer_id = 1
    list_str = []
    message = ""

    for current_row in Staging.objects.all():
        answers = []
        message += 'INSERT INTO QUESTIONS_ALL_QUESTIONS(id,TITLE, AREA, IMAGE, times_used, times_incorrect, correct_percentage) VALUES (\''
        message += unicode(question_id) + "','" + current_row.question + "','" + current_row.area + "','" +current_row.image + "',0,0,0" + ");" 
        
        
        if (current_row.answer_1):
            message += 'INSERT INTO QUESTIONS_ALL_ANSWERS(id,question_id, answer) VALUES (\''  + unicode(answer_id) + "','" + unicode(question_id) + "','" + unicode(current_row.answer_1) + "');"

            
            if (current_row.correct_answer_1 == '1' or 
                current_row.correct_answer_2 == '1'or
                current_row.correct_answer_3 == '1' or 
                current_row.correct_answer_4 == '1' ):
                
                message += 'INSERT INTO QUESTIONS_CORRECT_ANSWERS(id,question_id, answer_id) VALUES (\''+ unicode(correct_answer_id) + "','" + unicode(question_id) + "','" +  unicode(answer_id) + "');"
                correct_answer_id += 1
            answer_id += 1
                
        if (current_row.answer_2):
            message += 'INSERT INTO QUESTIONS_ALL_ANSWERS(id,question_id, answer) VALUES (\''+ unicode(answer_id) + "','" + unicode(question_id) + "','"  + unicode(current_row.answer_2) + "');"

            if (current_row.correct_answer_1 == '2' or 
                current_row.correct_answer_2 == '2' or
                current_row.correct_answer_3 == '2' or 
                current_row.correct_answer_4 == '2' ):
                
                message += 'INSERT INTO QUESTIONS_CORRECT_ANSWERS(id,question_id, answer_id) VALUES (\''+ unicode(correct_answer_id) + "','" + unicode(question_id) + "','" +  unicode(answer_id) + "');"
                correct_answer_id += 1
            answer_id += 1
                
        if (current_row.answer_3):
            message += 'INSERT INTO QUESTIONS_ALL_ANSWERS(id,question_id, answer) VALUES (\''  + unicode(answer_id) + "','"+ unicode(question_id)+ "','"  + unicode(current_row.answer_3) + "');"

            if (current_row.correct_answer_1 == '3' or 
                current_row.correct_answer_2 == '3' or
                current_row.correct_answer_3 == '3' or 
                current_row.correct_answer_4 == '3' ):
                
                message += 'INSERT INTO QUESTIONS_CORRECT_ANSWERS(id,question_id, answer_id) VALUES (\''+ unicode(correct_answer_id) + "','" + unicode(question_id) + "','" +  unicode(answer_id) + "');"
                correct_answer_id += 1
            answer_id += 1
            
        if (current_row.answer_4):
            message += 'INSERT INTO QUESTIONS_ALL_ANSWERS(id,question_id, answer) VALUES (\'' + unicode(answer_id) + "','"  + unicode(question_id)+ "','" + unicode(current_row.answer_4) + "');"

            if (current_row.correct_answer_1 == '4' or 
                current_row.correct_answer_2 == '4' or
                current_row.correct_answer_3 == '4' or 
                current_row.correct_answer_4 == '4' ):
                
                message += 'INSERT INTO QUESTIONS_CORRECT_ANSWERS(id,question_id, answer_id) VALUES (\''+ unicode(correct_answer_id) + "','" + unicode(question_id) + "','" +  unicode(answer_id) + "');"
                correct_answer_id += 1
            answer_id += 1
            
        if (current_row.answer_5):
            message += 'INSERT INTO QUESTIONS_ALL_ANSWERS(id,question_id, answer) VALUES (\''  + unicode(answer_id) + "','" + unicode(question_id) + "','" + unicode(current_row.answer_5) + "');"

            if (current_row.correct_answer_1 == '5' or 
                current_row.correct_answer_2 == '5' or
                current_row.correct_answer_3 == '5' or 
                current_row.correct_answer_4 == '5' ):
                
                message += 'INSERT INTO QUESTIONS_CORRECT_ANSWERS(id,question_id, answer_id) VALUES (\''+ unicode(correct_answer_id) + "','" + unicode(question_id) + "','" +  unicode(answer_id) + "');"
                correct_answer_id += 1
            answer_id += 1
            
        if (current_row.answer_6):
            message += 'INSERT INTO QUESTIONS_ALL_ANSWERS(id,question_id, answer) VALUES (\'' + unicode(answer_id) + "','" + unicode(question_id) + "','"  + unicode(current_row.answer_6) + "');"

            if (current_row.correct_answer_1 == '6' or 
                current_row.correct_answer_2 == '6' or
                current_row.correct_answer_3 == '6' or 
                current_row.correct_answer_4 == '6' ):
                
                message += 'INSERT INTO QUESTIONS_CORRECT_ANSWERS(id,question_id, answer_id) VALUES (\''+ unicode(correct_answer_id) + "','" + unicode(question_id) + "','" +  unicode(answer_id) + "');"
                correct_answer_id += 1
            answer_id += 1
            
        if (current_row.answer_7):
            message += 'INSERT INTO QUESTIONS_ALL_ANSWERS(id,question_id, answer) VALUES (\'' + unicode(answer_id) + "','" + unicode(question_id) + "','"  + unicode(current_row.answer_7) + "');"

            if (current_row.correct_answer_1 == '7' or 
                current_row.correct_answer_2 == '7' or
                current_row.correct_answer_3 == '7' or 
                current_row.correct_answer_4 == '7' ):
                
                message += 'INSERT INTO QUESTIONS_CORRECT_ANSWERS(id,question_id, answer_id) VALUES (\''+ unicode(correct_answer_id) + "','" + unicode(question_id) + "','" +  unicode(answer_id) + "');"
                correct_answer_id += 1
            answer_id += 1
            
        if (current_row.answer_8):
            message += 'INSERT INTO QUESTIONS_ALL_ANSWERS(id,question_id, answer) VALUES (\''  + unicode(answer_id) + "','" + unicode(question_id) + "','" + unicode(current_row.answer_8) + "');"

            if (current_row.correct_answer_1 == '8' or 
                current_row.correct_answer_2 == '8' or
                current_row.correct_answer_3 == '8' or 
                current_row.correct_answer_4 == '8' ):
                
                message += 'INSERT INTO QUESTIONS_CORRECT_ANSWERS(id,question_id, answer_id) VALUES (\''+ unicode(correct_answer_id) + "','" + unicode(question_id) + "','" +  unicode(answer_id) + "');"
                correct_answer_id += 1
            answer_id += 1
  
        question_id += 1
    #message = " ".join(list_str)
    return render_to_response("staging.html", locals())

        

        
        